home *** CD-ROM | disk | FTP | other *** search
- ; ARITH.ASM
- ;
- ; A simple recursive descent parser for arithmetic strings.
-
- .xlist
- include stdlib.a
- includelib stdlib.lib
- .list
-
-
- dseg segment para public 'data'
-
- ; Grammar for simple arithmetic grammar (supports +, -, *, /):
- ;
- ; E -> FE'
- ; E' -> + F E' | - F E' | <empty string>
- ; F -> TF'
- ; F' -> * T F' | / T F' | <empty string>
- ; T -> G | (E)
- ; G -> H | H G
- ; H -> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
- ;
-
-
- InputLine byte 128 dup (0)
-
- dseg ends
-
- cseg segment para public 'code'
- assume cs:cseg, ds:dseg
-
- ; Matching functions for the grammar.
- ; These functions return the carry flag set if they match their
- ; respective item. They return the carry flag clear if they fail.
- ; If they fail, they preserve di. If they succeed, di points to
- ; the first character after the match.
-
-
- ; E -> FE'
-
- E proc near
- push di
- call F
- jnc E_Failed
- call EPrime
- jnc E_Failed
- add sp, 2 ;Success, don't restore di.
- stc
- ret
-
- E_Failed: pop di
- clc
- ret
- E endp
-
-
-
- ; E' -> + F E' | - F E' | <empty string>
-
- EPrime proc near
- push di
- cmp byte ptr es:[di], '+'
- jne TryMinus
- inc di
- call F
- jnc EP_Failed
- call EPrime
- jnc EP_Failed
- Success: add sp, 2
- stc
- ret
-
- TryMinus: cmp byte ptr es:[di], '-'
- jne Success
- inc di
- call F
- jnc EP_Failed
- call EPrime
- jnc EP_Failed
- add sp, 2
- stc
- ret
-
- EP_Failed: pop di
- stc
- ret
- EPrime endp
-
-
-
- ; F -> TF'
-
- F proc near
- push di
- call T
- jnc F_Failed
- call FPrime
- jnc F_Failed
- add sp, 2 ;Success, don't restore di.
- stc
- ret
-
- F_Failed: pop di
- clc
- ret
- F endp
-
-
-
-
- ; F -> * T F' | / T F' | <empty string>
-
- FPrime proc near
- push di
- cmp byte ptr es:[di], '*'
- jne TryDiv
- inc di
- call T
- jnc FP_Failed
- call FPrime
- jnc FP_Failed
- Success: add sp, 2
- stc
- ret
-
- TryDiv: cmp byte ptr es:[di], '/'
- jne Success
- inc di
- call T
- jnc FP_Failed
- call FPrime
- jnc FP_Failed
- add sp, 2
- stc
- ret
-
- FP_Failed: pop di
- stc
- ret
- FPrime endp
-
-
- ; T -> G | (E)
-
- T proc near
- call G
- jnc TryParens
- ret
-
- TryParens: push di
- cmp byte ptr es:[di], '('
- jne T_Failed
- inc di
- call E
- jnc T_Failed
- cmp byte ptr es:[di], ')'
- jne T_Failed
- inc di
- add sp, 2
- stc
- ret
-
- T_Failed: pop di
- clc
- ret
- T endp
-
-
- ; The following is a free-form translation of
- ;
- ; G -> H | H G
- ; H -> 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
-
- G proc near
- cmp byte ptr es:[di], '0'
- jb G_Failed
- cmp byte ptr es:[di], '9'
- ja G_Failed
-
- DigitLoop: inc di
- cmp byte ptr es:[di], '0'
- jb G_Succeeds
- cmp byte ptr es:[di], '9'
- jbe DigitLoop
- G_Succeeds: stc
- ret
-
- G_Failed: clc
- ret
- G endp
-
-
- Main proc
- mov ax, seg dseg ;Set up the segment registers
- mov ds, ax
- mov es, ax
-
- printf
- byte "Enter an arithmetic expression: ",0
- lesi InputLine
- gets
- call E
- jnc BadExp
-
- ; Good so far, but are we at the end of the string?
-
- cmp byte ptr es:[di], 0
- jne BadExp
-
- ; Okay, it truly is a good expression at this point.
-
- printf
- byte "'%s' is a valid expression",cr,lf,0
- dword InputLine
- jmp Quit
-
- BadExp: printf
- byte "'%s' is an invalid arithmetic expression",cr,lf,0
- dword InputLine
-
- Quit: ExitPgm
- Main endp
-
- cseg ends
-
- sseg segment para stack 'stack'
- stk byte 1024 dup ("stack ")
- sseg ends
-
- zzzzzzseg segment para public 'zzzzzz'
- LastBytes byte 16 dup (?)
- zzzzzzseg ends
- end Main
-